/**
 * copyright (c) 2017-2023 厦门风领科技有限公司
 * 
 * 发行SDK
 * zengbinsi
 * 2022-03-14
 * 2023-10-23 20:22:33
 */

if (gg.isMiniGame || gg.isQuickGame || gg.isH5) {
    gg.log('load mini-game-sdk');
    const sdk = {};
    let sdkConfig = {
        subscriptionIds: [],     // 订阅ID
    };
    let serverConfig = {
        // 是否开启埋点功能（0和3表示关闭，其它表示打开）
        SWITCH_SEND_ANALYSIS: 4,
        // ------基础配置--------
        /**屏蔽总开关*/
        shareSwitch: 1,
        /**服务端地区屏蔽*/
        regionSwitch: 1,
        /**审核屏蔽开关*/
        reviewSwitch: 0,
        /**Ip屏蔽*/
        configUserIp: 1,
        /**低端机降帧开关*/
        OPEN_DIPEIBAN: 4,
        /**流程开关*/
        SWITCH_PAGE_PROCESS: 1,
        /**广告加载吐司开关*/
        SWITCH_SHOW_VIDEO_TOAST: 3,
        // ------屏外刷新--------
        /**刷新开关*/
        SWITCH_SHOW_LEFT_BANNER: 3,
        /**刷新时间*/
        LEFT_BANNER_UPDATE_TIME: 30,
        /**刷新次数*/
        LEFT_BANNER_UPDATE_COUNT: 3,

        // ------banner自动刷新--------
        /**自动刷新间隔*/
        BANNER_UPDATE_INTERVAL: 30,

        // ------广告拉取上限--------
        /**视频拉取次数上限*/
        PLAY_VIDEO_MAX: 30,
        /**banner拉取次数上限*/
        BANNER_LOAD_MAX: 15,

        // ------强拉视频--------
        /**loading强拉视频*/
        SWITCH_GAME_START_VIDEO: 3,
        /**开始游戏强拉视频*/
        SWITCH_GAME_START2_VIDEO: 3,
        /**【视频】前置原生盒子页2强拉视频*/
        SWITCH_FIRST_BOX2_VIDEO: 3,
        /**【视频】原生盒子页1强拉视频*/
        SWITCH_GAME_tbs_VIDEO: 3,
        /**【视频】原生盒子页2强拉视频*/
        SWITCH_GAME_BOX2_VIDEO: 3,
        SWITCH_GAME_BOX1_VIDEO: 3,
        /**流程内强拉*/
        SWITCH_VIDEO_PAGE: 3,

        // ------强拉插屏--------
        /**前置原生盒子页2强拉插屏*/
        SWITCH_FRONT_BOX2_INTERSTITAL: 3,
        /**首页强拉插屏*/
        SWITCH_HOME_INTERSTITAL: 3,
        /**游戏页强拉插屏*/
        SWITCH_GAME_INTERSTITAL: 3,
        /**原生盒子页1强拉插屏*/
        SWITCH_BOX1_INTERSTITAL: 3, //原生盒子页强拉视频和强拉插屏同时拉取时,先拉取插屏再拉取视频
        /**原生盒子页2强拉插屏*/
        SWITCH_BOX2_INTERSTITAL: 3, //原生盒子页强拉视频和强拉插屏同时拉取时,先拉取插屏再拉取视频
        /**流程内强拉*/
        SWITCH_INTERSTITIAL_PAGE: 3,

        // ------前置原生盒子页--------
        /**前置原生盒子页1*/
        SWITCH_SHOW_FRONT_BOX1: 4,
        /**前置原生盒子页2*/
        SWITCH_SHOW_FRONT_BOX2: 4,
        /**前置原生盒子页1按钮延迟出现时间*/
        SWITCH_BUTTON_DELAY_FRONT_BOX1: 0,
        /**前置原生盒子页2按钮延迟出现时间*/
        SWITCH_BUTTON_DELAY_FRONT_BOX2: 0,
        /**前置原生盒子页1banner开关*/
        SWITCH_SHOW_FRONT_BOX1_BANNER: 3,
        /**前置原生盒子页2banner开关*/
        SWITCH_SHOW_FRONT_BOX2_BANNER: 3,
        /**前置原生盒子页1banner类型*/
        SWITCH_TYPE_FRONT_BOX2_BANNER: 1,//1:banner , 2:仿banner图片

        // ------抽屉页--------
        /**首页抽屉弹窗开关*/
        SWITCH_DRAWER_HOME_PAGE: 3,
        /**游戏页抽屉弹窗开关*/
        SWITCH_DRAWER_GAME_PAGE: 3,

        // ------首页--------
        /**游戏首页开关*/
        SWITCH_SHOW_HOME: 4,
        /**是否启用快速刷新Banner*/
        SWITCH_QUICK_UPDATE_BANNER: 3,
        /**快速刷新Banner次数*/
        QUICK_UPDATE_BANNER_COUNT: 3,
        /**快速刷新Banner时间间隔*/
        QUICK_UPDATE_BANNER_INTERVAL: 4,
        /**首页banner开关*/
        SWITCH_SHOW_HOME_BANNER: 3,
        /**首页banner类型*/
        SWITCH_TYPE_HOME_BANNER: 1,
        /**首页左边原生广告*/
        SWITCH_SHOW_HOMEL_NATIVEAD: 3,
        /**首页右边原生广告*/
        SWITCH_SHOW_HOMER_NATIVEAD: 3,
        /**全局顶部原生*/
        GLOBAL_NATIVE: 3,
        /**首页原生广告开关*/
        SWITCH_SHOW_HOME_NATIVEAD: 3,
        /**抽屉页开关*/
        SWITCH_DRAWER_HOME_PAGE: 3,

        // ------游戏页--------
        /**游戏页原生开关*/
        SWICH_SHOW_GAME_NATIVEAD: 3,
        /**游戏页banner开关*/
        SWITCH_SHOW_GAME_BANNER: 3,
        /**游戏页banner类型*/
        SWITCH_TYPE_GAME_BANNER: 1, // 1:banner , 2:仿banner图片
        /**游戏页左侧多原生广告*/
        SWITCH_SHOW_GAMEL_NATIVEAD: 3,
        /**游戏页右侧多原生广告*/
        SWITCH_SHOW_GAMER_NATIVEAD: 3,
        /**游戏页左侧单原生广告*/
        SWITCH_SHOW_GAMEL2_NATIVEAD: 3,
        /**游戏页右侧单原生广告*/
        SWITCH_SHOW_GAMER2_NATIVEAD: 3,
        /**抽屉页开关*/
        SWITCH_DRAWER_GAME_PAGE: 3,

        // ------原生盒子页--------
        /**原生盒子页1*/
        SWITCH_SHOW_BOX1: 4,
        /**原生盒子页2*/
        SWITCH_SHOW_BOX2: 4,
        /**原生盒子页1按钮延迟出现时间*/
        SWITCH_BUTTON_DELAY_BOX1: 0,
        /**原生盒子页2按钮延迟出现时间*/
        SWITCH_BUTTON_DELAY_BOX2: 0,
        /**原生盒子页1banner开关*/
        SWITCH_SHOW_BOX1_BANNER: 3,
        /**原生盒子页2banner开关*/
        SWITCH_SHOW_BOX2_BANNER: 3,
        /**原生盒子页1banner类型*/
        SWITCH_TYPE_BOX2_BANNER: 1, // 1:banner , 2:仿banner图片
        /**【原生】原生盒子页1广告类型*/
        SWITCH_AD_BOX1_TYPE: 1,//用于控制原生盒子页1中间默认展示的广告类型1:矩阵原生   2:多banner
        /**【原生】原生盒子页2广告类型*/
        SWITCH_AD_BOX2_TYPE: 1,//用于控制原生盒子页1中间默认展示的广告类型1:矩阵原生   2:多banner
        /**【原生】前置盒子页1广告类型*/
        SWITCH_AD_FRONT_BOX1_TYPE: 1,//用于控制原生盒子页1中间默认展示的广告类型1:矩阵原生   2:多banner
        /**【原生】前置盒子页2广告类型*/
        SWITCH_AD_FRONT_BOX2_TYPE: 1,//用于控制原生盒子页1中间默认展示的广告类型1:矩阵原生   2:多banner

        // ------原生盒子页误触（前置与后置共用开关）--------
        /**原生盒子页1误触开关*/
        TBS_SWITCH_BOX1: 3,
        /**原生盒子页1误触方式切换开关*/
        TBS_TYPE_BOX1: 2, //1:上跳误触,2:激活误触
        /**原生盒子页1误触间隔*/
        TBS_INTERVAL_BOX1: 0,  //0:每局出现
        /**原生盒子页1误触上限*/
        TBS_MAX_BOX1: 10,
        /**原生盒子页1误触从第几局开始*/
        TBS_OFFSET_BOX1: 0,  //0:第一局
        /**原生盒子页1上跳误触延迟时间*/
        TBS_INTERVAL_BOX1_JUMP: 2,
        /**原生盒子页1激活误触延迟时间*/
        TBS_INTERVAL_BOX1_DELAY: 2,
        /**原生盒子页2误触开关*/
        TBS_SWITCH_BOX2: 3,
        /**原生盒子页2误触方式切换开关*/
        TBS_TYPE_BOX2: 2, //1:上跳误触,2:激活误触
        /**原生盒子页2误触间隔*/
        TBS_INTERVAL_BOX2: 0, //0:每局出现
        /**原生盒子页2误触上限*/
        TBS_MAX_BOX2: 10,
        /**原生盒子页2误触从第几局开始*/
        TBS_OFFSET_BOX2: 0, //0:第一局
        /**原生盒子页2上跳误触延迟时间*/
        TBS_INTERVAL_BOX2_JUMP: 2,
        /**原生盒子页2激活误触延迟时间*/
        TBS_INTERVAL_BOX2_DELAY: 2,

        // ------误触页--------
        /**疯狂点击误触开关*/
        TBS_SWITCH_CRY: 3,
        /**疯狂点击误触间隔*/
        TBS_INTERVAL_CRY: 0,//0:每局出现
        /**疯狂点击误触上限*/
        TBS_MAX_CRY: 10,
        /**疯狂点击误触从第几局开始*/
        TBS_OFFSET_CRY: 0, //0:第一局
        /**误触页进度条每次点击减少多少*/
        SWITCH_CRY_AD_REDUCE: 0.15,
        /**误触页进度条小于多少时拉取广告*/
        SWITCH_CRY_AD_RATIO: 0.8,
        /**误触页视频广告出现概率*/
        SWITCH_CRY_AD_TYPE: 1, //1:只出现视频, 0:只出现banner,介于0-1之间时即为视频的概率
        /**误触页延迟跳转时间*/
        MISS_TO_TIME: 2,
        /**误触页banner出现次数*/
        SWITCH_CRY_BANNER_COUNT: 3,
        /**视频误触布局1概率*/
        SWITCH_CRY_PAGE_TYPE: 0.7,

        // ------结算页--------
        /**结算页banner开关*/
        SWITCH_SHOW_RESULT_BANNER: 3,
        /**游戏页banner类型*/
        SWITCH_TYPE_RESULT_BANNER: 1, //1:banner , 2:仿banner图片
        /**结算页原生开关*/
        SWITCH_SHOW_RESULT_NATIVEAD: 3,
        /**结算页左侧原生开关*/
        SWITCH_SHOW_SCOREL_NATIVEAD: 3,
        /**结算页右侧原生开关*/
        SWITCH_SHOW_SCORER_NATIVEAD: 3,
        /**结算页开关*/
        SWITCH_SHOW_RESULT: 4,

        // ------结算页误触--------
        /**结算页误触开关*/
        TBS_SWITCH_RESULT: 3,
        /**结算页误触方式切换开关*/
        TBS_TYPE_RESULT: 1, //1:上跳误触,2:激活误触
        /**结算页误触间隔*/
        TBS_INTERVAL_RESULT: 0,  //0:每局出现
        /**结算页误触上限*/
        TBS_MAX_RESULT: 10,
        /**结算页误触从第几局开始*/
        TBS_OFFSET_RESULT: 0, //0:第一局
        /**结算页上跳误触延迟时间*/
        TBS_INTERVAL_RESULT_JUMP: 2,
        /**结算页激活误触延迟时间*/
        TBS_INTERVAL_RESULT_DELAY: 2,

        /**误触页按钮类型*/
        TBS_TYPE_NATIVE_BOX1: 4,
        TBS_TYPE_NATIVE_BOX2: 4,

        // ------UI开关--------
        /**首页-更多好玩*/
        SWITCH_HOME_MORE: null,
        /**开关-金币UI显示*/
        SWITCH_COIN_UI_SHOW: null,
        /**开关-首页开始游戏按钮显示*/
        SWITCH_HOME_STARTBTN_SHOW: null,
        /**开关-首页LOGO按钮显示*/
        SWITCH_HOME_LOGOBTN_SHOW: null,
        /**开关-首页遮罩显示*/
        SWITCH_HOME_MASK_SHOW: null,
        /**开关-游戏页关卡显示*/
        SWITCH_SHOW_GAME_LEVEL: null,
        /**游戏加载页开关*/
        SWITCH_SHOW_LOADING: 4,

        // ------其他--------
        /**原生广告预加载等待时间*/
        NATIVEAD_PRELOAD_WAIT_INTERVAL: 2,
        //假开关
        BOX_SWITCH: 4,
        BOX2_SWITCH: 4,
        // -----OPPO------
        /**首页互推九宫格是否自动弹出*/
        HOME_BOX_SWITCH: 3,
        /**首页互推盒子自动弹出第几局开始*/
        HOME_BOX_ENABLEDLEVEL: 1,
        /**首页互推盒子自动弹出间隔几局*/
        HOME_BOX_INTERVAL: 0,
        /**添加至桌面图标是否自动弹出*/
        HOME_DESKTOP_ICON_SWITCH: 3,
        /**首页banner广告显示*/
        HOME_SHOW_BANNER: 3,
        /**游戏页内插屏原生广告是否显示*/
        GAME_NATIVE_AD_SWITCH: 3,
        /**游戏页原生广告显示第几局开始*/
        GAME_NATIVE_AD_ENABLEDLEVEL: 1,
        /**游戏页原生广告显示间隔几关*/
        GAME_NATIVE_AD_INTERVAL: 0,
        /**大按钮是否有实际关闭功能*/
        AD_NATIVE_BIGBTNCLOSE: 3,
        /**小按钮是否延迟开关*/
        AD_NATIVE_CLOSE_SWITCH: 3,
        /**原生广告关闭小按钮延迟时间设置开关*/
        AD_NATIVE_CLOSE_DELAY: 3,
        /**手势引导开关*/
        AD_NATIVE_FINGER: 3,
        /**游戏页屏外原生曝光:屏蔽开关*/
        TBS_INTERVAL_LEFT: 3,
        /**游戏页屏外原生曝光:刷新时间*/
        LEFT_ORIGINAL_UPDATE_TIME: 5,
        /**游戏页屏外原生曝光:刷新次数*/
        LEFT_ORIGINAL_UPDATE_COUNT: 5,
        /**游戏页屏外原生曝光:第几局开始*/
        TBS_OFFSET_ORIGINAL_UPDATE: 1,
        /**宝箱页继续游戏按钮强拉原生广告*/
        BOX_NATIVE_FORCE_SWITCH: 3,
        /**宝箱页第几关强拉原生广告开关*/
        BOX_NATIVE_FORCE_ENABLEDLEVEL: 3,
        /**宝箱页强拉原生广告间隔几局*/
        BOX_NATIVE_FORCE_INTERVAL: 0,
        /**神秘宝箱关闭按钮是否延迟出现*/
        BOX_CLOSE_SWITCH: 3,
        /**神秘宝箱关闭按钮延迟时间*/
        BOX_CLOSE_DELAY: 3,
        /**神秘宝箱继续游戏按钮是否延迟出现*/
        BOX_CONTINUE_SWITCH: 3,
        /**神秘宝箱继续按钮延迟时间*/
        BOX_CONTINUE_DELAY: 3,
        /**宝箱页原生广告是否显示*/
        BOX_NATIVE_AD_SWITCH: 3,
        /**宝箱页原生广告显示第几局开始*/
        BOX_NATIVE_AD_ENABLEDLEVEL: 3,
        /**宝箱页原生广告显示间隔*/
        BOX_NATIVE_AD_INTERVAL: 3,
        /**是否强拉添加至桌面图标*/
        BOX_DESKTOP_ICON_SWITCH: 3,
        /**第几关开始强拉*/
        BOX_DESKTOP_ICON_ENABLEDLEVEL: 3,
        /**添加桌面图标强拉间隔关卡*/
        BOX_DESKTOP_ICON_INTERVAL: 3,
        /**是否显示宝箱页*/
        SHOW_BOX_PAGE: 3,
        /**结算页继续游戏按钮强拉原生广告*/
        RESULT_NATIVE_FORCE_SWITCH: 3,
        /**结算页第几关强拉原生广告开关*/
        RESULT_NATIVE_FORCE_ENABLEDLEVEL: 3,
        /**结算页强拉原生广告间隔几局*/
        RESULT_NATIVE_FORCE_INTERVAL: 3,
        /**结算页继续游戏按钮是否延迟出现*/
        RESULT_CONTINUE_SWITCH: 3,
        /**结算页继续按钮延迟时间*/
        RESULT_CONTINUE_DELAY: 3,


        // -----VIVO------
        /** 首页原生模板广告显示开关【地区屏蔽】*/
        HOME_NATIVE_TEMPLATE_SWITCH: 3,
        /** 首页原生模板广告第几次进入显示*/
        HOME_NATIVE_TEMPLATE_ENABLEDLEVEL: 2,
        /** 首页原生模板广告显示间隔*/
        HOME_NATIVE_TEMPLATE_INTERVAL: 0,
        /** 首页banner显示开关*/
        HOME_BANNER_SWITCH: 3,
        /** 体力值上限*/
        STRENGTH_MAX: 10,

        /** 自动增加体力的时间间隔*/
        ADD_STRENGTH_INTERVAL: 300,
        // ADD_STRENGTH_INTERVAL: 10,

        /** 游戏页原生模板广告显示开关【地区屏蔽】*/
        GAME_NATIVE_TEMPLATE_SWITCH: 3,
        /** 游戏页原生模板广告第几次进入显示*/
        GAME_NATIVE_TEMPLATE_ENABLEDLEVEL: 2,
        /** 游戏页原生模板广告显示间隔*/
        GAME_NATIVE_TEMPLATE_INTERVAL: 0,
        /** 游戏页banner显示开关*/
        GAME_BANNER_SWITCH: 3,
        /** 宝箱视频icon显示*/
        BOX_VIDEO_SWITCH: 3,
        /**宝箱打勾按钮是否默认打勾*/
        BOX_CHECK_VIDEO: 4,
        /** 宝箱关闭按钮是否延迟出现*/
        BOX_CLOSE_SWITCH: 4,
        /** 宝箱关闭按钮延迟显示时间*/
        BOX_CLOSE_DELAY: 3,
        /** 宝箱页是否显示*/
        BOX_SWITCH: 4,
        /**宝箱页banner显示开关**/
        BOX_BANNER_SWITCH: 3,
        /** 宝箱页原生模板广告显示开关*/
        BOX_NATIVE_TEMPLATE_SWITCH: 3,
        /** 宝箱页原生模板广告延迟显示开关【地区屏蔽】 */
        BOX_NATIVE_TEMPLATE_DELAY_SWITCH: 4,
        /** 宝箱页原生模板广告延迟出现时间*/
        BOX_NATIVE_TEMPLATE_DELAY_TIME: 1,
        /**是否强拉添加至桌面图标【地区屏蔽】*/
        BOX_DESKTOP_ICON_SWITCH: 3,
        /**第几关开始强拉添加桌面图标*/
        BOX_DESKTOP_ICON_ENABLEDLEVEL: 1,
        /**添加桌面图标强拉间隔关卡*/
        BOX_DESKTOP_ICON_INTERVAL: 0,
        /** 结算页原生模板广告显示开关*/
        RESULT_NATIVE_TEMPLATE_SWITCH: 3,
        /** .结算页原生模板广告延迟显示开关【地区屏蔽】 */
        RESULT_NATIVE_TEMPLATE_DELAY_SWITCH: 4,
        /** 结算页原生模板广告延迟出现时间*/
        RESULT_NATIVE_TEMPLATE_DELAY_TIME: 1,
        /**结算页横幅显示开关*/
        RESULT_BANNER_SWITCH: 3,
        /**结算页点击继续游戏是否回到首页*/
        REACH_HOME_SWITCH: 4,
        /**控制原生模板广告与顶部的距离*/
        AD_NATIVE_DISTANCE: 100,
        /**九宫格广告距顶部的距离*/
        AD_BOX_DISTANCE: 300,


        // -----QQ------
        /**首页盒子自动弹出的开关*/
        HOME_BOX_SWITCH: 3,
        /**首页盒子广告自动弹出第几局开始*/
        HOME_BOX_ENABLEDLEVEL: 2,
        /**首页盒子强拉间隔几局*/
        HOME_BOX_INTERVAL: 0,
        /**首页banner显示开关*/
        HOME_BANNER_SWITCH: 3,
        /**banner自动刷新开关*/
        BANNER_RENOVATE_SWITCH: 3,
        /**banner自动刷新时间*/
        BANNER_RENOVATE_TIME: 10,
        /**banner自动刷新次数上限*/
        BANNER_REFRESH_COUNT: 15,
        /**首页体力值加号直接观看视频开关*/
        HOME_PLUS_VIDEO_SWITCH: 3,
        /**体力值上限*/
        STRENGTH_MAX: 10,
        /**自动增加体力的时间间隔*/
        ADD_STRENGTH_INTERVAL: 300,
        /**首页积木广告显示开关*/
        HOME_RECOMMEND_SWITCH: 3,
        /**狂点宝箱页1显示开关*/
        TBS_SWITCH_BOX: 3,
        /**狂点宝箱页1第几关开始弹出*/
        TBS_BOX_ENABLEDLEVEL: 2,
        /**狂点宝箱页1显示间隔*/
        TBS_BOX_INTERVAL: 0,
        /**狂点宝箱页1点击区域切换*/
        BOX_CLICK_SWITCH: 4,
        /**狂点宝箱页1视频与banner比率*/
        BOX_VIDEO_RATIO: 0.5,
        /**游戏页banner广告显示开关*/
        GAME_BANNER_SWITCH: 3,
        /**游戏页积木广告显示开关*/
        GAME_RECOMMEND_SWITCH: 3,
        /**狂点宝箱页2显示开关*/
        TBS_SWITCH_BOX2: 3,
        /**狂点宝箱页2第几关开始弹出*/
        TBS_BOX2_ENABLEDLEVEL: 2,
        /**狂点宝箱页2显示间隔*/
        TBS_BOX_INTERVAL: 0,
        /**狂点宝箱页2点击区域切换*/
        BOX2_CLICK_SWITCH: 4,
        /**狂点宝箱页2视频与banner比率*/
        BOX2_VIDEO_RATIO: 0.5,
        /**结算页盒子自动弹出的开关*/
        RESULT_BOX_SWITCH: 3,
        /**.结算页盒子广告自动弹出第几局开始*/
        RESULT_BOX_ENABLEDLEVEL: 2,
        /**结算页盒子强拉间隔几局*/
        RESULT_BOX_INTERVAL: 0,
        /**结算页继续游戏按钮强拉视频开关*/
        RESULT_FORCE_VIDEO_SWITCH: 3,
        /**结算页继续游戏按钮强拉视频第几次开始*/
        RESULT_FORCE_VIDEO_ENABLEDLEVEL: 1,
        /**结算页继续游戏按钮强拉视频间隔*/
        RESULT_FORCE_VIDEO_INTERVAL: 0,
        /**结算页继续游戏按钮是否跳转首页开关*/
        REACH_HOME_SWITCH: 3,
        /**结算页积木广告显示开关*/
        REACH_RECOMMEND_SWITCH: 3,

        /**好友上线提醒 */
        FRIEND_ONLINE: 9,
        /**排名下降提醒 */
        RANK_DOWN: 12,
        /**好友邀请提醒 */
        FRIEND_INVITE: 20
    };

    // 订阅ID
    let subscriptionIds = [{
        id: 'soIirflGiH367zd6SJj3zmh-qPoCDAG2YdT5EX4Ydec',
        count: (serverConfig && serverConfig.FRIEND_ONLINE) || 9
    }, {
        id: 'd1osViA90-GcBIxb4hfl_p0SC33Q4r686Uw6Y05LZ-Q',
        count: (serverConfig && serverConfig.RANK_DOWN) || 12
    }, {
        id: 'mwffpSIVWI4IqZamzxGNOAkysbv54afmhgZUQdmLPTA',
        count: (serverConfig && serverConfig.FRIEND_INVITE) || 20
    }];

    const adBannerConfigs = [];
    const adRewardedVideoConfigs = [];
    const adInterstitialConfigs = [];
    const adNativeConfigs = [];
    const adPortalConfigs = [];
    const adBlockConfigs = [];
    const adVivoNativeConfigs = [];
    const boxBannerConfigs = [];

    const adConfigs = {};
    // 广告视图缓存
    const adViewCaches = {};
    const shareConfig = {};
    const hiedCaches = [];

    let isDebug = false;
    let isPortrait = true;
    let isLogined = false;
    let reviewSwitch = false;
    let eReviewSwitch = false;
    let APP_SERVER_HOST = '';
    let APP_SERVER_HOST_NEW = '';
    let APP_SERVER_HOST_ANALYSIS = '';
    const cryptoKey = 'U2FsdGVkX19FFjBDia5ba4D4R9ddZO1RqYjzUl6ss6s=';
    let launchOptions = { query: {} };
    let systemInfo = {};


    // 字节投放参数
    const ttAdParams = {};
    // 用户数据
    const userData = {};
    window.userData = userData;

    const EventName = {
        UPDATE_SERVER_CONFIG: 'update_server_config',
        UPDATE_AD_CONFIG: 'update_ad_config',
        LOGIN_SUCCESSED: 'LOGIN_SUCCESSED',
    };
    const AdType = {
        BANNER: 'BANNER',
        REWARDED_VIDEO: 'REWARDED_VIDEO',
        INTERSTITIAL: 'INTERSTITIAL',
        NATIVE: 'NATIVE',
        CUSTOM: 'CUSTOM',
        PORTAL: 'PORTAL',//九宫格
        BLOCK: 'BLOCK',//积木
        OPPO_NATIVE: 'OPPO_NATIVE',
        VIVO_NATIVE: 'VIVO_NATIVE',
        VIVO_BOXBANNER: 'VIVO_BOXBANNER',
    };

    /**格子位置类型*/
    const CustomType = {
        //格子广告
        NARIVE_TOP: 'NARIVE_TOP',//原生头部
        NARIVE_BOTTOM: 'NARIVE_BOTTOM',//原生底部
        NARIVE_MIDDLE: 'NARIVE_MIDDLE',//原生中心
        NARIVE_MIDDLE_NARIVE: 'NARIVE_MIDDLE_NARIVE',//结算页中心原生
        NARIVE_LEFT_MANY: 'NARIVE_LEFT',//原生默认多格子左边
        NARIVE_RIGHT_MANY: 'NARIVE_RIGHT_MANY',//原生默认多格子右边
        NARIVE_LEFT_SINGL: 'NARIVE_LEFT_SINGL',//原生左边单格子
        NARIVE_RIGHT_SINGL: 'NARIVE_RIGHT_SINGL',//原生右边单格子
        NARIVE_LEFT_MANY_SINGL: 'NARIVE_LEFT_MANY_SINGL',//原生左边带有单格子的多格子的广告
        NARIVE_RIGHT_MANY_SINGL: 'NARIVE_RIGHT_MANY_SINGL',//原生右边带有单格子的多格子的广告

        //banner
        BANNER_BOTTOM: 'BANNER_BOTTOM',//底部banner广告
    };

    const updateLaunchOptions = () => {
        launchOptions = gg.getLaunchOptionsSync() || { query: {} };
        launchOptions.query = launchOptions.query || {};
    };
    gg.onShow(() => { updateLaunchOptions(); });




    const onlineEstimate = () => {
        gg._gameStartTime = gg._gameStartTime || Date.now();
        /** 游戏开始时间 */
        gg.gameStartTime = gg.gameStartTime || (() => { return Math.floor(gg._gameStartTime / 1000); });
        gg.getRunTime = gg.getRunTime || ((isMS) => {
            const runTime = Date.now() - gg._gameStartTime;
            return isMS ? runTime : Math.floor(runTime / 1000);
        });

        setInterval(() => {
            sdk.sendEvent('online_estimate', {
                duration: 180,
                start: gg.gameStartTime(),
                online_module: '',
            });
        }, 3 * 60 * 1000);
    };



    // ==========================================================================================
    // 网络请求
    // ==========================================================================================
    const sendWarning = (url, msg) => {
        const getTodayValue = (key, defaultVal) => {
            const date = new Date();
            let day = date.getFullYear() + '_' + (date.getMonth() + 1) + '_' + date.getDate();
            return gg.getStorageSync(key + '_' + day) || defaultVal;
        };

        const gameBad = getTodayValue(`_gameBad`, 0);
        console.log('gameBad', gameBad);
        if (gameBad) {
            console.log('return');
            return;
        }

        console.log('setTodayValue');
        let postObj = null;
        if (gg.isQuickGameOPPO || gg.isQuickGameVIVO) {
            postObj = {
                name: sdkConfig.GAME_NAME,
                appid: sdkConfig.APP_KEY,
            };
        } else {
            postObj = {
                name: sdkConfig.GAME_NAME,
                appid: sdkConfig.APP_ID,
                url,
                msg,
            };
        }
        isDebug && gg.log('postObj', postObj);

        try {
            sdk.post('https://warning.feigo.fun/api/warning/game-bad', { postObj }, {}, true);
        } catch (error) { }
    };

    const sendRequerst = (type, router, params, headParams, callback) => {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            const DONE = 4;
            if (xhr.readyState !== DONE) { return; }
            if (!xhr.responseText) { return; }
            if (xhr.status >= 200 && xhr.status < 400) {
                let res;

                try {
                    res = JSON.parse(xhr.responseText);

                } catch (error) {
                    return callback(error, undefined);
                }

                callback(undefined, res || xhr.responseText);
            } else {
                callback(xhr.responseText ? JSON.parse(xhr.responseText) : xhr, undefined);
                console.log('testxhr.status', xhr.status);
                xhr.status > 499 && sendWarning(router, xhr.responseText);
            }
        };

        xhr.open(type, router, true);
        //设置提交数据的方式,application/json json传输数据用的比较多
        xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
        xhr.setRequestHeader("client-os", cc.sys.os);
        xhr.setRequestHeader("x-access-token", userData.token || '');
        xhr.setRequestHeader("client-ver", sdkConfig.APP_VERSION);


        if (gg.isQuickGameOPPO || gg.isQuickGameVIVO) {
            xhr.setRequestHeader("appid", sdkConfig.APP_KEY);
        } else {
            xhr.setRequestHeader("appid", sdkConfig.APP_ID);
        }
        // 字节投放用户到微信小游戏
        if (ttAdParams.clue_token && ttAdParams.ad_id && ttAdParams.creative_id) {
            xhr.setRequestHeader('clue_token', window['clue_token']);
            xhr.setRequestHeader('ad_id', window['ad_id']);
            xhr.setRequestHeader('creative_id', window['creative_id']);
        }

        if (headParams) {
            for (var key in headParams) {
                if (key === "Content-Type" || key === "client-os" || key === "client-ver" || key === "x-access-token") { continue; }
                xhr.setRequestHeader(key, headParams[key]);
            }
        }

        try {
            if (type === 'GET') {
                xhr.send();
            } else {
                xhr.send(JSON.stringify(params));
            }
        } catch (error) {
            gg.error(error);
            callback && callback(error);
        }
    };

    sdk.get = (router, headParams) => {
        return new Promise((resolve, reject) => {
            sendRequerst('GET', router, {}, headParams, (err, res) => {
                err ? reject(err) : resolve(res);
            });
        });
    };

    sdk.post = (router, params, headParams, unuseEncrypt) => {
        headParams = headParams || {};
        let encryptionParams = params || {};
        encryptionParams["timestamp"] = gg.isEmptyString(userData.timestamp) ? undefined : userData.timestamp;
        encryptionParams["rand"] = Number(`${Date.now()}`.substring(3) + Math.floor(Math.random() * 10000000000));
        headParams['area-no'] = sdkConfig.AREA_NO || 1;
        router.indexOf('pre-config') === -1 && !gg.isEmptyString(userData.accessToken) && (headParams['H-A-T'] = userData.accessToken);
        if (isDebug || unuseEncrypt) {
            headParams['crypto-debug'] = sdkConfig.cryptoDebug || 'cszrnsq9a6';
        } else {
            encryptionParams = { "ciphertext": CryptoJS.AES.encrypt(JSON.stringify(encryptionParams), sdkConfig.secret || cryptoKey).toString() };
        }

        return new Promise((resolve, reject) => {
            sendRequerst('POST', router, encryptionParams, headParams, (err, res) => {
                if (err) { return reject(err); }
                if (res.err === 3 || res.err === 510) {
                    if (res.data) {
                        const bytes = CryptoJS.AES.decrypt(res.data, sdkConfig.secret || cryptoKey);
                        const bytesStr = bytes.toString(CryptoJS.enc.Utf8);
                        const obj = JSON.parse(bytesStr) || bytesStr;
                        res.data = obj ? obj : {};
                    }
                } else if (res.err === 4) {

                } else if (res.err === 509) {
                    updateTimestamp().then(() => {
                        try {
                            const res = sdk.post(router, params, headParams, unuseEncrypt);
                            resolve(res);
                        } catch (error) {
                            reject(error);
                        }
                    });
                }
                resolve(res.data || res);
            });
        });
    };

    // ==========================================================================================
    // 获取配置
    // ==========================================================================================

    const getPreConfigFromeServer = async (callback) => {
        if (gg.isQuickGameOPPO || gg.isQuickGameVIVO) { return; }
        const launchOptions = gg.getLaunchOptionsSync();
        try {
            let res = await sdk.get(`${APP_SERVER_HOST}/api/config/pre-config`, {
                scene: launchOptions.scene,
                appid: sdkConfig.APP_ID,
            });
            res = res.data || res;
            isDebug && gg.log('getPreConfigFromeServer:', res);
            res = gg.parseJSON(res);

            window.reviewSwitch = reviewSwitch = res.reviewSwitch;
            window.eReviewSwitch = eReviewSwitch = res.eReviewSwitch;
            window.uiPattern = Number(res.uiPattern);
            window.isShowBox = res.isShowBox;
            window.isShowBoxBySceneTag = res.isShowBoxBySceneTag;
            window.isHideGameBoxButton = res.isHideGameBoxButton || 0;

            callback && callback(undefined, res.data);
        } catch (error) {
            gg.error('getPreConfigFromeServer error:', error);
            window.reviewSwitch = window.eReviewSwitch = 1;
            callback && callback(undefined, { reviewSwitch: 1, eReviewSwitch: 1, ...error });
        }
    };
    const getPreConfigFromeServerNew = async (callback) => {
        if (gg.isQuickGameOPPO || gg.isQuickGameVIVO) { return; }
        const launchOptions = gg.getLaunchOptionsSync();
        try {
            let res = await sdk.post(`${APP_SERVER_HOST_NEW}/config/mh/leisure-pre-config`, {
                areaNo: sdkConfig.AREA_NO,
                clientVersion: sdkConfig.APP_VERSION,
                scene: launchOptions.scene,
                appid: sdkConfig.APP_ID,
            });
            res = res.data || res;
            isDebug && gg.log('getPreConfigFromeServerNew:', res);
            res = gg.parseJSON(res);

            res.reviewSwitch = res.reviewSwitch ? 1 : 0; // 开关类型，返回bool值
            res.eReviewSwitch = res.reviewSwitch; // 服务端未实现，默认和reviewSwitch一致
            res.uiPattern = 0; // 服务端未实现，默认0

            window.reviewSwitch = reviewSwitch = res.reviewSwitch;
            window.eReviewSwitch = eReviewSwitch = res.eReviewSwitch;
            window.uiPattern = Number(res.uiPattern);
            window.isShowBox = res.isShowBox;
            window.isShowBoxBySceneTag = res.isShowBoxBySceneTag;
            window.isHideGameBoxButton = res.isHideGameBoxButton || 0;

            callback && callback(undefined, res.data);
        } catch (error) {
            gg.error('getPreConfigFromeServerNew error:', error);
            window.reviewSwitch = window.eReviewSwitch = 1;
            callback && callback(undefined, { reviewSwitch: 1, eReviewSwitch: 1, ...error });
        }
    };

    const getServerConfigsFromServer = async () => {
        try {
            const launchOptions = gg.getLaunchOptionsSync();
            const res = await sdk.get(`${APP_SERVER_HOST}/api/config/config`, {
                scene: launchOptions.scene,
                'client-ver': sdkConfig.APP_VERSION,
                'client-os': cc.sys.os,
                is_first: userData.first || 0,
            });
            isDebug && gg.log('获取后台开关配置成功', res);
            // 验证配置是否完善
            // if (gg.isEmpty(res['SWITCH_SEND_ANALYSIS'])) { throw new Error('ServerConfig.SWITCH_SEND_ANALYSIS is empty'); }

            // 合并服务端和本地配置,服务端覆盖本地配置
            serverConfig = { ...serverConfig, ...sdkConfig.configData, ...res };
            isDebug && gg.log('getServerConfigsFromServer:res,获取后台开关配置成功', serverConfig);
            if (!window.serverConfig) { window.serverConfig = { ...serverConfig }; }

            let ab_test = false;
            if (gg.isMiniGameWX) {
                if (serverConfig.AB_TEST) {
                    if (serverConfig.AB_TEST_ALL_USER) {
                        ab_test = true;
                    }
                    const regtime = gg.userData.regtime;
                    const timeStamp = serverConfig.AB_TEST_REGTIME_TIMESTAMP;
                    const divisor = serverConfig.AB_TEST_REGTIME_DIV_COUNT || 2;
                    let isBUser = (regtime % divisor == 0);
                    if (regtime >= timeStamp) {
                        ab_test = isBUser;
                    }
                }
                const testTags = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
                const abTestTag = testTags[userData.abTestTag] || 'Z';
                console.log(`后台配置判断，是${abTestTag}测试用户`, userData.abTestTag);
                sdk.sendEvent("userSetOnce", {
                    ab_test: abTestTag
                }, "userSetOnce");
            }

            serverConfig.reviewSwitch = res.reviewSwitch || 0;
            window.PLAY_VIDEO_MAX = res.PLAY_VIDEO_MAX || 20;
            // 是否强制更新版本
            window.flForceUpdateVersion = !!res.flForceUpdateVersion || false;
            window.flForceUpdateVersion && gg.checkUpdateVersion();
            !!res.isDebug && cc.debug.setDisplayStats(true);

            gg.systemEvent.emit(EventName.UPDATE_SERVER_CONFIG, serverConfig['reviewSwitch']);

            // 统计
            if (res.reviewSwitch && gg.compareVersion(sdkConfig.APP_VERSION, res.proVersion) > 0) {
                // 获取启动参数
                const launchOptions = gg.getLaunchOptionsSync();
                if (launchOptions.scene !== 1030) {
                    sdk.sendEvent('进入审核版本', { scene: launchOptions.scene, userTag: userData.userTag });
                }
            }

            // 测试环境允许上报埋点，方便排查bug
            // if (!isDebug && gg.isMiniGameWX && window.__wxConfig.envVersion !== 'release') {
            //     serverConfig.SWITCH_SEND_ANALYSIS = 0;
            //     gg.warn('关闭埋点开关！！！');
            // }
        } catch (error) {
            gg.error('update server config error:', error);
        }
    };

    const getAdConfigsFromServer = async () => {
        try {
            const res = await sdk.get(`${APP_SERVER_HOST}/api/config/banner-value`);
            isDebug && gg.log('getAdConfigsFromServer,获取广告配置成功', res);
            res.map(conf => {
                serverConfig[conf.key] = conf.value;
                adConfigs[conf.key] = conf.value;
                switch (conf.type) {
                    case 1: adBannerConfigs.push(conf.value); break;
                    case 2: adRewardedVideoConfigs.push(conf.value); break;
                    case 3: adInterstitialConfigs.push(conf.value); break;
                    case 4: adNativeConfigs.push(conf.key); break;
                    case 5: adBlockConfigs.push(conf.value); break;
                    case 6: adPortalConfigs.push(conf.value); break;
                    case 8: adVivoNativeConfigs.push(conf.value); break;
                    case 10: boxBannerConfigs.push(conf.value); break;
                    default: break;
                }
            });
            gg.systemEvent.emit(EventName.UPDATE_AD_CONFIG, adConfigs);
        } catch (error) {
            gg.error('update ad config error:', error);
        }
        //2秒后强制加载完成
        setTimeout(() => { gg.systemEvent.emit(EventName.UPDATE_AD_CONFIG); }, 2000);
    };
    const getAdConfigsFromServerNew = async () => {
        try {
            const res = await sdk.post(`${APP_SERVER_HOST_NEW}/config/mh/get-leisure-ad`);
            isDebug && gg.log('getAdConfigsFromServer,获取广告配置成功', res);
            res.map(conf => {
                // 新的超休广告配置和旧超休广告配置，id和value的值互换了(这里广告id在id字段中，value只是个序号)
                serverConfig[conf.key] = conf.id;
                adConfigs[conf.key] = conf.id;
                switch (conf.type) {
                    case 1: adBannerConfigs.push(conf.id); break;
                    case 2: adRewardedVideoConfigs.push(conf.id); break;
                    case 3: adInterstitialConfigs.push(conf.id); break;
                    case 4: adNativeConfigs.push(conf.key); break;
                    case 5: adBlockConfigs.push(conf.id); break;
                    case 6: adPortalConfigs.push(conf.id); break;
                    case 8: adVivoNativeConfigs.push(conf.id); break;
                    case 10: boxBannerConfigs.push(conf.id); break;
                    default: break;
                }
            });
            gg.systemEvent.emit(EventName.UPDATE_AD_CONFIG, adConfigs);
        } catch (error) {
            gg.error('update ad config error:', error);
        }
        //2秒后强制加载完成
        setTimeout(() => { gg.systemEvent.emit(EventName.UPDATE_AD_CONFIG); }, 2000);
    };

    const onUpdateShareConfig = (res) => {
        // 设置分享参数
        shareConfig.shareId = res.share_id;
        shareConfig.shareTitle = res.share_title;
        shareConfig.shareImgUrl = res.share_img;
        if (res.logo_status !== 1 && res.client_logo && res.client_logo !== '') {
            shareConfig.shareImgUrl = res.client_logo;
        }
        const shareQuery = `share_id=${shareConfig.shareId}&share_tag=胶囊菜单&invite_tag=${userData.userTag}`;
        gg.onShareAppMessage(() => {
            return {
                title: shareConfig.shareTitle,
                imageUrl: shareConfig.shareImgUrl,
                query: shareQuery
            };
        });
        gg.showShareMenu({
            withShareTicket: false,
            menus: ['shareAppMessage', 'shareTimeline'],
            success: (res) => { gg.log('显示分享菜单成功：', res); },
            fail: (err) => { gg.log('显示分享菜单失败：', err); },
        });
        if (res.activity_id !== null && res.activity_id !== undefined && gg.isMiniGameWX) {
            gg.updateShareMenu({
                isUpdatableMessage: true,
                activityId: res.activity_id,
                templateInfo: {
                    parameterList: [
                        {
                            name: 'member_count',
                            value: `${res.member_count || 3124123}`
                        }, {
                            name: 'room_limit',
                            value: `${res.room_limit || 4312412}`
                        }
                    ],
                }
            });
        }
    };
    const getShareParamsFromServer = async () => {
        try {
            const res = await sdk.get(`${APP_SERVER_HOST}/api/config/share-config`);
            isDebug && console.log('getShareParamsFromServer,获取分享配置成功', res);
            onUpdateShareConfig(res);
        } catch (error) {
            gg.error('getShareParamsFromServer error:', error);
        }
    };
    const getShareParamsFromServerNew = async () => {
        try {
            const res = await sdk.post(`${APP_SERVER_HOST_NEW}/config/mh/get-leisure-share`);
            isDebug && console.log('getShareParamsFromServer,获取分享配置成功', res);

            const data = {
                share_id: res.value,
                share_title: res.text,
                share_img: res.imageUrl,
                client_logo: res.clientUrl,
                logo_status: Number(res.type), // 1服务端，2客户端
            }

            onUpdateShareConfig(data);
        } catch (error) {
            gg.error('getShareParamsFromServer error:', error);
        }
    };




    // ==========================================================================================
    // 登录
    // ==========================================================================================
    const initUserData = (res) => {
        userData.nickname = res.nickname || res.nickName || '';
        userData.avatar = res.avatar || res.avatarUrl || '';
        userData.gender = res.gender || 0;
        userData.openId = res.openid || '';
        userData.unionId = res.unionid || '';
        userData.province = res.province;       // 省份
        userData.city = res.city;

        userData.userId = res.user_id || '';
        userData.userTag = res.user_tag || '';
        userData.token = res.token || '';
        userData.accessToken = res.accessToken || '';

        userData.etag = res.etag || res.channel || '';
        userData.euid = res.euid || '';
        userData.channel = res.channel || '';
        if (gg.isMiniGame) { userData.channel = 'wx'; }
        if (gg.isMiniGameQQ) { userData.channel = 'qq'; }
        if (gg.isMiniGameTT) { userData.channel = 'tt'; }
        if (gg.isQuickGameOPPO) { userData.channel = 'oppo'; }
        if (gg.isQuickGameVIVO) { userData.channel = 'vivo'; }

        userData.first = res.first || res.is_first || 0;
        userData.regtime = res.regtime || (Math.floor(Date.now() / 1000));
        userData.isTodayReg = isToday(res.regtime);
        userData.abTestTag = res.abTest || res.ab_test || 0;
        userData.shareId = launchOptions.query.share_id;

        let sub_channel_id = gg.isMiniGameTT ? "53101" : (gg.isMiniGameQQ ? "53107" : "9977");
        userData.sub_channel_id = gg.isEmptyString(window['_sub_channel_id']) ? sub_channel_id : window['_sub_channel_id'];

        let aid = undefined;
        if (launchOptions.query.weixinadinfo) { aid = launchOptions.query.weixinadinfo.split('.')[0]; }

        sdk.setEventCommonParams('device_id', userData.userTag);

        const testTags = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
        const abTestTag = testTags[userData.abTestTag] || 'Z';
        console.log(`后台配置判断，是${abTestTag}测试用户`, userData.abTestTag);
        sdk.sendEventUserSetOnce({
            openid: userData.openId,
            ab_test: abTestTag,
            first_login_time: userData.regtime,
            register_time: userData.regtime,
            appid: sdkConfig.APP_ID,
            channel: userData.channel,
            channel_id: userData.sub_channel_id,
            etag: userData.etag,
            from_ad_id: launchOptions.query.ad_id || aid || '',
            from_advertiser_id: launchOptions.query.advertiser_id || launchOptions.query.gdt_vid || '',
            from_creative_id: launchOptions.query.creative_id || '',
            from_scene: launchOptions.scene,
            from_share_role_id: launchOptions.query.invite_tag || '',
            from_share_tag: launchOptions.query.share_tag || '',
            role_id: userData.userTag,
            role_name: userData.userTag,
            source_appid: launchOptions.referrerInfo ? launchOptions.referrerInfo.appId : '',
        });

        sdk.sendEventUserSet({
            last_login_time: (Math.floor(Date.now() / 1000)),
        });
    };

    const updateTimestamp = async () => {
        const res = await sdk.post(`${APP_SERVER_HOST_NEW}/prop/mh/sync-time`);
        userData.timestamp = res;
    };
    const roleLogin = async (accessToken) => {
        const roleLoginRes = await sdk.post(`${APP_SERVER_HOST_NEW}/account/mh/role-login`, {
            accessToken,
            gameAreaNo: sdkConfig.AREA_NO,
            index: 0
        });
        userData.accessToken = roleLoginRes.accessToken;
        userData.timestamp = roleLoginRes.timestamp;
        setInterval(async () => {
            updateTimestamp();
        }, 180 * 1000);
    };

    const onLoginSuccessed = async (res, accessToken) => {
        initUserData(res);
        sdk.sendEvent('account_login', { from_scene: launchOptions.scene }, undefined, true);

        if (!gg.getStorageSync(`first_${userData.userTag}`, 0) && !userData.first) {
            // 删除包后再登录
            sdk.sendEvent('user_data_loser');
        }
        // 不管新用户老用户,全部打上标签
        gg.setStorageSync(`first_${userData.userTag}`, 1);
        // 缓存用户标识
        gg.setStorageSync('openId', res.openid);

        // 获取服务端配置
        if (sdkConfig.useNewServer) {
            await roleLogin(accessToken);
            getAdConfigsFromServerNew();
        } else {
            getAdConfigsFromServer();
        }
        getServerConfigsFromServer();
        isLogined = true;

        // 登录成功事件
        gg.systemEvent.emit(EventName.LOGIN_SUCCESSED, userData);
    };

    // 获取OPPO、vivo的etag值
    const getETagOnQuickGame = () => {
        let etag = '', adid, clickid, creativeid, creativetype, source_aid;
        const launchOption = qg.getLaunchOptionsSync()
        const extraData = launchOption.referrerInfo.extraData;
        if (extraData) { // 1105版本及以上
            adid = extraData.adid;
            // clickid = extraData.clickid; 
            // creativeid = extraData.creativeid; 
            // creativetype = extraData.creativetype; 
            // source_aid = extraData.source_aid; 
            etag = extraData.adid;
        } else { // 1105以下版本
            const internal = launchOption.query.internal;
            const channel = internal && internal.channel ? internal.channel : '';//获取来源，判断是否为deeplink
            if (channel === "deeplink") {
                const custom_params = internal.custom_params;//获取到dp启动来源参数
                console.log(custom_params);
                const url = JSON.parse(custom_params).cus_origin_uri;  // 获取源启动的URL 字符串
                adid = url.match(/adid=([^&]+)/)[1];  // 使用正则表达式提取 adid 参数，若匹配不到则为空
                // clickid = url.match(/clickid=([^&]+)/)[1];  // 使用正则表达式提取clickid 参数，若匹配不到则为空
                // creativeid = url.match(/creativeid=([^&]+)/)[1];  // 使用正则表达式提取 creativeid，若匹配不到则为空 
                // creativetype = url.match(/creativetype=([^&]+)/)[1];  // 使用正则表达式提取 creativetype 参数，若匹配不到则为空
                // source_aid = url.match(/source_aid=([^&]+)/)[1];  // 使用正则表达式提取 source_aid，若匹配不到则为空
                etag = adid;
            }
        }
        return etag;
    };
    const getLoginParams = (code) => {
        let loginParams = {};
        let etag = '', gdt_vid = '', aid = '', source_etag = '';

        // 获取微信小游戏广点通广告参数
        launchOptions.query.etag && (etag = launchOptions.query.etag);
        launchOptions.query.gdt_vid && (gdt_vid = launchOptions.query.gdt_vid);
        launchOptions.query.weixinadinfo && (aid = launchOptions.query.weixinadinfo.split('.')[0]);

        // 非广告跳转过来的，etag采取来源appId覆盖
        if (gdt_vid === '' && launchOptions.referrerInfo) {
            etag = launchOptions.referrerInfo.package || launchOptions.referrerInfo.appId || '';
        }
        // 微信小游戏来源.
        if (launchOptions.referrerInfo) {
            source_etag = launchOptions.referrerInfo.appId || 'null';
        }
        // 获取从字节投放到微信小游戏参数
        if (launchOptions.query) {
            ttAdParams['clue_token'] = launchOptions.query.clue_token;
            ttAdParams['ad_id'] = launchOptions.query.ad_id;
            ttAdParams['creative_id'] = launchOptions.query.creative_id;
        }
        // 获取抖音小游戏直投参数
        if (gg.isMiniGameTT) {
            // 抖音1.0接口是adid，如果取到就是1.0投放计划，如果没取到取promotionid，抖音2.0接口是promotionid
            loginParams.adid = query.promotionid;
            loginParams.clickid = query.clickid;
            loginParams.custom_advertiser_id = query.custom_advertiser_id;
            loginParams.advertiser_id = query.advertiser_id;
        }

        if (gg.isQuickGameVIVO || gg.isQuickGameOPPO) {
            loginParams = {
                code,
                pkgName: sdkConfig.PACKAGE_NAME,
                etag: getETagOnQuickGame(),
            };
        } else {
            loginParams.gdt_vid = gdt_vid;
            loginParams.aid = aid;
            loginParams.code = code;
            loginParams.etag = etag;
            loginParams.source_etag = source_etag;
            loginParams.invite_tag = launchOptions.query.invite_tag;
            loginParams.share_id = launchOptions.query.share_id;
            loginParams.type = launchOptions.query.type;
            loginParams.scene = launchOptions.scene;
        }

        return loginParams;
    };

    const loginByCode = async (code, params, resolve, reject) => {
        try {
            const loginParams = getLoginParams(code);
            isDebug && gg.log('SDK login params:', loginParams, `${APP_SERVER_HOST}/api/code-login`);
            const res = await sdk.post(`${APP_SERVER_HOST}/api/code-login`, loginParams, {}, true);
            gg.log('code login succ:', res);
            await onLoginSuccessed(res);
            params && params.callback && params.callback(undefined, userData);
            resolve && resolve(res);
        } catch (error) {
            isDebug && gg.log('登录失败:', error);
            params && params.callback && params.callback(error);
            reject && reject(error);
        }
    };

    const loginByCodeNew = async (code, params, resolve, reject) => {
        try {
            const loginParams = getLoginParams(code);
            loginParams.appid = sdkConfig.APP_ID;
            loginParams.host = APP_SERVER_HOST;
            gg.log('SDK login params:', `${APP_SERVER_HOST_NEW}/account/mh/login`, loginParams);
            const res = await sdk.post(`${APP_SERVER_HOST_NEW}/account/mh/login`, {
                appAreaNo: sdkConfig.AREA_NO,
                leisure: loginParams,
            });

            isDebug && gg.log('code login succ:', res);
            await onLoginSuccessed(res.leisure, res.accessToken);
            params?.callback?.(undefined, userData);
            resolve?.(res);
        } catch (error) {
            isDebug && gg.error('登录失败:', error);
            params?.callback?.(error);
            reject?.(error);
        }
    };

    const loginByOpenId = async (openId, params, resolve, reject) => {
        let etag = '';

        if (gg.isQuickGameOPPO) {
            etag = launchOptions.referrerInfo ? launchOptions.referrerInfo.package : '';
        }

        try {
            const loginParams = {
                openId,
                openid: openId,
                pkgName: sdkConfig.PACKAGE_NAME,
                etag,
            };

            isDebug && gg.log('SDK login params:', loginParams);
            const res = await sdk.post(`${APP_SERVER_HOST}/api/code-login`, loginParams, {}, true);
            gg.log('openId login succ:', res);
            await onLoginSuccessed(res);
            params && params.callback && params.callback(undefined, userData);
            resolve && resolve(res);
        } catch (error) {
            isDebug && gg.error('登录失败:', error);
            params && params.callback && params.callback(error);
            reject && reject(error);
        }
    };

    const login = (params) => {
        if (gg.isH5) { return gg.log('此平台没有登入功能'); }
        return new Promise((resolve, reject) => {
            if (isLogined) {
                isDebug && gg.error('SDK login:', '已登录！！！');
                params && params.callback && params.callback(undefined, userData);
                return resolve && resolve(userData);
            }

            const success = (res) => {
                let code = res.code;
                if (!code) { code = res.anonymousCode; }
                if (!code && (res.data || res.token)) {
                    code = res.token ? res.token : (res.data ? res.data.token : "");
                }
                isDebug && gg.log('SDK login success:', res);
                if (sdkConfig.useNewServer) {
                    loginByCodeNew(code, params, resolve, reject);
                } else {
                    loginByCode(code, params, resolve, reject);
                }
            };

            const fail = (err) => {
                // vivo未授权用户登录处理
                if (gg.isQuickGameVIVO) {
                    isDebug && gg.log('vivo未授权用户登录采用OpenId进行登录。');
                    const openId = gg.getStorageSync('openId', '');
                    return loginByOpenId(openId, params, resolve, reject);
                }

                gg.error('SDK login fail:', err);
                params && params.callback && params.callback(err);
                reject(err);
            };

            gg.login({ success, fail });
        });
    };




    // ==========================================================================================
    // 广告
    // ==========================================================================================

    /** 
     * 设置广告样式
     *  @param site 位置类型
     */
    const getAdStyle = (site) => {
        const style = {};
        const visibleSize = cc.view.getVisibleSize();
        const frameSize = cc.view.getFrameSize();
        const ratioW = frameSize.width / visibleSize.width;
        const screenL = frameSize.width > frameSize.height;
        let positionGap = null;
        switch (site) {
            case CustomType.NARIVE_TOP:
                positionGap = getCustomGap({ fullHeight: 0, height: 0 });
                style.left = frameSize.width / 2 - 180;
                style.top = positionGap.heightGap;

                if (gg.isMiniGameQQ) {
                    if (screenL) {
                        style.top = 10;
                    } else {
                        style.left = frameSize.width / 2 - 102;
                        positionGap = getCustomGap({ fullHeight: 30, height: 0 });
                        style.top = positionGap.heightGap;
                    }
                }
                break;
            case CustomType.NARIVE_LEFT_MANY:
                style.top = frameSize.width / 2;
                style.left = 10 * ratioW;
                if (screenL) { style.top = frameSize.height / 2 * ratioW - 50; }
                if (gg.isMiniGameQQ) {
                    style.left = 15;
                    style.top = frameSize.height / 2 - 102;
                }
                break;
            case CustomType.NARIVE_MIDDLE:
                positionGap = getCustomGap({ fullWidth: 200, width: 150 });
                style.left = 0;
                style.top = positionGap.widthGap - 100;
                if (screenL) {
                    style.left = frameSize.width / 2 - 187;
                    style.top = -40;
                    style.width = 375;
                }
                break;
            case CustomType.NARIVE_MIDDLE_RESULT:
                positionGap = getCustomGap({ fullWidth: 200, width: 150 });
                style.left = 0;
                style.top = positionGap.widthGap;
                if (screenL) {
                    style.left = frameSize.width / 2 - 187;
                    style.top = -40;
                    style.width = 375;
                }
                break;
            case CustomType.NARIVE_RIGHT_MANY:
                style.left = frameSize.width - 72;
                style.top = frameSize.width / 2;
                if (screenL) { style.top = frameSize.height / 2 * ratioW - 50; }
                if (gg.isMiniGameQQ) {
                    style.left = frameSize.width - 90;
                    style.top = frameSize.height / 2 - 102;
                }
                break;
            case CustomType.NARIVE_LEFT_SINGL:
                style.left = 10 * ratioW;
                style.top = frameSize.width / 2 - 53;
                if (screenL) { style.top = frameSize.height / 2 * ratioW - 110; }
                break;
            case CustomType.NARIVE_LEFT_MANY_SINGL:
                style.left = 10 * ratioW;
                style.top = frameSize.width / 2 + 53;
                if (screenL) { style.top = frameSize.height / 2 * ratioW - 10; }
                break;
            case CustomType.NARIVE_RIGHT_SINGL:
                style.left = frameSize.width - 72;
                style.top = frameSize.width / 2 - 53;
                if (screenL) { style.top = frameSize.height / 2 * ratioW - 110; }
                break;
            case CustomType.NARIVE_RIGHT_MANY_SINGL:
                style.left = frameSize.width - 72;
                style.top = frameSize.width / 2 + 53;
                if (screenL) { style.top = frameSize.height / 2 * ratioW - 10; }
                break;
            case CustomType.BANNER_BOTTOM:
                let height = 255;
                if (gg.isMiniGameQQ) { height = 180; }
                if (gg.isQuickGameOPPO) { height = 110; };
                if (gg.isQuickGameVIVO) { height = 100; };

                let top = visibleSize.height - height;
                style.left = 0;
                style.width = frameSize.width;
                style.top = top * ratioW;

                if (screenL) {
                    if (gg.isMiniGameQQ) {
                        style.left = frameSize.width / 2 - 195;
                    } else if (gg.isQuickGameVIVO) {
                        style.left = frameSize.width / 4 + 30;
                    } else if (gg.isMiniGameWX) {
                        style.width = null;
                        style.left = frameSize.width / 2 - 180;
                        style.top = top * ratioW + 10;
                    }
                }
                break;
            default: break;
        }
        return style;
    };

    /**
     * 获取格子位子差值
     * 全面屏宽度,全面屏高度,非全屏宽度,非全屏屏高度
     * @param {*, fullWidth, fullHeight , width , height } params 
     */
    const getCustomGap = (params) => {
        // //默认差值为非全面屏
        const positionGap = {};
        positionGap.heightGap = params.height;
        positionGap.widthGap = params.width;
        if (cc.view.getFrameSize().height / cc.view.getFrameSize().width >= 2) {
            positionGap.heightGap = params.fullHeight;
            positionGap.widthGap = params.fullWidth;
        }
        return positionGap;
    };

    const getAdUnitId = (adType, isCacheFirst) => {
        let adUnitIds = [];
        switch (adType) {
            case AdType.BANNER: adUnitIds = adBannerConfigs; break;
            case AdType.REWARDED_VIDEO: adUnitIds = adRewardedVideoConfigs; break;
            case AdType.INTERSTITIAL: adUnitIds = adInterstitialConfigs; break;
            case AdType.CUSTOM: adUnitIds = adNativeConfigs; break;
            case AdType.PORTAL: adUnitIds = adPortalConfigs; break;
            case AdType.BLOCK: adUnitIds = adBlockConfigs; break;
            case AdType.VIVO_NATIVE: adUnitIds = adVivoNativeConfigs; break;
            case AdType.VIVO_BOXBANNER: adUnitIds = boxBannerConfigs; break;
            default: break;
        }
        const index = Math.floor(Math.random() * adUnitIds.length);
        const adUnitId = adUnitIds[index];

        return adUnitId;
    };

    /**发送视频看完的统计 */
    const sendWatchVideo = () => {
        //记录当日新增用户数据
        try {
            sdk.get(`${APP_SERVER_HOST}/api/user/watch-video-log/${gg.isEmptyString(userData.etag) ? 'null' : userData.etag}`, {
                'x-access-token': userData.token,
                'client-ver': sdkConfig.APP_VERSION,
                'client-os': cc.sys.os,
            });
        } catch (err) {
            console.warn('sendWatchVideo error:', err);
        }
    }

    const bindAdEvent = (adView, params) => {
        isDebug && console.log('bindAdEvent', adView);

        if (adView.onLoad) {
            adView.onLoad((res) => {
                if (res && res.adList) { adView.adid = res.adList[0].adId; }
                params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_load_succ', {
                    positionTag: params.positionTag || '',
                    scatter: params.scatter,
                });
                adView.reportAdShow && adView.reportAdShow({ adId: adView.adUnitId });
                if (gg.isMiniGameQQ && params.adType === AdType.BLOCK) { adView.show(); }
                adView.adLoadCallback && adView.adLoadCallback(undefined, res || { msg: 'ad load successed.', adView });
                adView.adLoadCallback = undefined;
            });
        }

        //oppo原生没有关闭接口
        if (adView.onClose) {
            adView.offClose();
            adView.onClose((res) => {
                //微信有自动load，vivo原生是销毁重新创建
                if (!gg.isMiniGameWX || params.adType !== AdType.VIVO_NATIVE) {
                    try {
                        isDebug && gg.log('广告关闭，重新加载');
                        adView.load();
                    } catch (error) {
                        isDebug && gg.log('重新加载失败', error);
                    }
                };

                if (res && !res.isEnded) {
                    gg.showToast({ title: '广告没有看完' });
                    params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_play_cancel', {
                        positionTag: params.positionTag || '',
                        scatter: params.scatter,
                    });
                } else {
                    if (params.adType === AdType.REWARDED_VIDEO) {
                        sdk.sendEvent('rewarded_video_play_end', {
                            positionTag: params.positionTag || '',
                            scatter: params.scatter,
                        });
                        sdk.sendEventUserSet({ total_ad_times: 1 });
                        // 视频统计
                        sendWatchVideo();
                    }
                }
                adView.adCloseCallback && adView.adCloseCallback(undefined, res || { msg: 'ad closed', adView });
                adView.adCloseCallback = undefined;
            });
        }

        if (adView.onError) {
            adView.onError((err) => {
                params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_error', {
                    errmsg: err.errMsg,
                    positionTag: params.positionTag || '',
                    scatter: params.scatter,
                });

                if (gg.isMiniGameWX) { onErrorVideoAd(err); }
                if (!err) { console.error('err'); return; }
                if (gg.isQuickGameOPPO && err && err.errMsg === "code: 10006,msg: ad data is null") { return console.log('err.errMsg =code: 10006'); }
                if (serverConfig.SWITCH_SHOW_VIDEO_TOAST !== 3) { gg.showToast({ title: '广告加载失败' }); }

                adView.adLoadCallback && adView.adLoadCallback(err);
                adView.adLoadCallback = undefined;
            });
        }

    };

    const onErrorVideoAd = (res) => {
        let msg;

        switch (res.errCode) {
            case 1000: msg = '后端接口调用失败，暂时无法观看'; break;
            case 1001: msg = '参数错误，暂时无法观看'; break;
            case 1002: msg = '广告单元无效，暂时无法观看'; break;
            case 1003: msg = '内部错误，暂时无法观看'; break;
            case 1004: msg = '无合适的广告，暂时无法观看'; break;
            case 1005: msg = '广告组件审核中，暂时无法观看'; break;
            case 1006: msg = '广告组件被驳回，暂时无法观看'; break;
            case 1007: msg = '广告组件被封禁，暂时无法观看'; break;
            case 1008: msg = '广告单元已关闭，暂时无法观看'; break;
            default: msg = '遇到未知错误，暂时无法观看'; break;
        }
        try {
            //发送流量主警告
            adSendWarning(res.errCode);
        } catch (error) { }
    };

    const adSendWarning = async (code = '-1000') => {
        let isSend = 0;
        const getTodayValue = (key, defaultVal) => {
            const date = new Date();
            let day = date.getFullYear() + '_' + (date.getMonth() + 1) + '_' + date.getDate();
            return gg.getStorageSync(key + '_' + day) || defaultVal;
        };
        const setTodayValue = (key, value) => {
            const date = new Date();
            let day = date.getFullYear() + '_' + (date.getMonth() + 1) + '_' + date.getDate();
            return gg.setStorageSync(key + '_' + day, value);
        };

        let BannerSendWaring = getTodayValue('BannerSendWaring', 0);
        if (BannerSendWaring) {
            return;
        }
        code = code.toString();
        switch (code) {
            case '1002':
            case '1005':
            case '1006':
            case '1007':
                isSend = 1;
                break;
        }
        if (isSend === 1 && BannerSendWaring === 0) {
            setTodayValue('BannerSendWaring', 1);
            try {
                sdk.post(`https://warning.feigo.fun/api/warning/flow-main`, {
                    name: sdkConfig.GAME_NAME,
                    appid: sdkConfig.APP_ID,
                    code: code
                }, {}, true);
            } catch (err) { }
        }
    };

    const getADViewInstance = (params) => {
        adViewCaches[params.adType] = adViewCaches[params.adType] || {};
        let adView = adViewCaches[params.adType][params.adUnitId];
        params.style = params.style || (params.site && getAdStyle(params.site)) || undefined;
        params.marginTop = params.marginTop || undefined;
        if (!adView || params.adType === AdType.BLOCK) {
            switch (params.adType) {
                case AdType.REWARDED_VIDEO: adView = gg.createRewardedVideoAd(params); break;
                case AdType.INTERSTITIAL: adView = gg.createInterstitialAd(params); break;
                case AdType.BANNER: adView = gg.createBannerAd(params); break;
                case AdType.NATIVE: adView = gg.createNativeAd(params); break;
                case AdType.CUSTOM: adView = gg.createCustomAd(params); break;
                case AdType.PORTAL: adView = gg.createGamePortalAd(params); break;
                case AdType.BLOCK: adView = gg.createBlockAd(params); break;
                case AdType.OPPO_NATIVE: adView = gg.createNativeAd(params); break;
                case AdType.VIVO_NATIVE: adView = getVivoNativeAd(params); break;
                case AdType.VIVO_BOXBANNER: adView = gg.createBoxBannerAd(params); break;
                default: break;
            }
            isDebug && console.log('create adView:', adView, params);
            adView.adUnitId = params.adUnitId;
            adView.configKey = params.configKey;
            adView.site = params.site;

            adViewCaches[params.adType][params.adUnitId] = adView;
            bindAdEvent(adView, params);
            if (!gg.isMiniGameWX) { adView.load && adView.load(); }
            hiedCaches.push(adView);
        } else {
            if (adView.configKey === params.configKey && adView.site !== params.site) {
                sdk.destroyAd(params, adView);
                adView = getADViewInstance(params);
            }
            if (adView.adType === AdType.VIVO_NATIVE) {
                sdk.destroyAd(params, adView);
                adView = getADViewInstance(params);
            }
            if (params.configKey === 'TouchBanner') {
                sdk.destroyAd(params, adView);
                adView = getADViewInstance(params);
            }
            if (adView.site === CustomType.NARIVE_MIDDLE) {
                adView.adLoadCallback = params.adLoadCallback;
                adView.adCloseCallback = params.adCloseCallback;
                bindAdEvent(adView, params);
            }
        }
        return adView;
    };

    const getVivoNativeAd = (params) => {
        const frameSize = cc.view.getFrameSize();
        const style = { top: serverConfig.AD_NATIVE_DISTANCE };
        if (frameSize.height < frameSize.width) {
            style.left = frameSize.width / 4 + 30;
        }
        params.style = style;
        return gg.createCustomAd(params);
    };

    /**
    * 销毁广告
    * @param {*, positionTag, adType } params 
    */
    sdk.destroyAd = (params, adView) => {
        if (!adView || !adView.destroy) { return gg.error('需要销毁的广告是空', adView); }
        if (!params || !params.adType) { return gg.error('销毁广告失败', params.adType); }
        adViewCaches[params.adType][adView.adUnitId] = null;
        adView.destroy();
    };

    sdk.hideAllVideo = () => {
        for (let index = 0; index < hiedCaches.length; index++) {
            hiedCaches[index] && hiedCaches[index].hide && hiedCaches[index].hide();
        }
    };




    // ==========================================================================================
    // 开放接口
    // ==========================================================================================

    /** 事件定义 */
    sdk.EventName = { ...EventName };
    /** 广告类型定义 */
    sdk.AdType = { ...AdType };
    /** 格子广告位置类型定义 */
    sdk.CustomType = { ...CustomType };
    // /** 获取游戏内容基础数据 */
    // sdk.getRemoteConfig = { ...serverConfig };

    /**
     * 初始化
     * @param { *, isDebug, APP_SERVER_HOST, APP_VERSION, AREA_NO, APP_ID, APP_KEY, GAME_NAME, PACKAGE_NAME, } config 
     */
    sdk.init = (config) => {
        sdkConfig = config;
        sdkConfig.AREA_NO = sdkConfig.AREA_NO || 1;
        APP_SERVER_HOST = config.APP_SERVER_HOST ?? 'https://game-api.feigo.fun';
        APP_SERVER_HOST_NEW = config.APP_SERVER_HOST_NEW ?? (sdkConfig.env === 'test' ? 'http://10.10.0.234:30099' : 'https://framework-prod-api.dengyou.net');
        APP_SERVER_HOST_ANALYSIS = config.APP_SERVER_HOST_ANALYSIS ?? 'https://shushu-log-prod.feigo.fun';
        isPortrait = cc.view.getVisibleSize().width < cc.view.getVisibleSize().height;
        serverConfig = { ...serverConfig, ...config.configData };
        isDebug = config.isDebug;
        gg.getAppId = () => { return sdkConfig.APP_ID; };
        console.log('isDebug', isDebug);
        isDebug && gg.log('SDK init:', config);

        onlineEstimate();
        // 五秒后强制加载完
        if (gg.isH5) return setTimeout(() => { gg.systemEvent.emit(EventName.UPDATE_AD_CONFIG); }, 5000);
        updateLaunchOptions();
        systemInfo = gg.getSystemInfoSync();

        initSendEvent();

        login({
            callback: (err, res) => {
                sdkConfig.useNewServer ? getShareParamsFromServerNew() : getShareParamsFromServer();
                // getShareParamsFromServer();
                config.callback && config.callback(err, res);
            }
        });
    };

    /**
     * 分享
     * @param { *, positionTag, callback } params 
     */
    sdk.share = (params) => {
        params = params || {};
        const { positionTag, callback } = params;
        const toCurrentGroup = gg.isEmpty(params.toCurrentGroup) ? (gg.isEmpty(shareConfig.toCurrentGroup) ? undefined : shareConfig.toCurrentGroup) : params.toCurrentGroup;
        const desc = params.desc || title || shareConfig.desc || undefined;
        const channel = params.channel || shareConfig.channel || undefined;

        if (gg.isMiniGameTT) {
            switch (channel) {
                case 0: params.channel = ''; break;
                case 1: params.channel = 'article'; break;
                case 2: params.channel = 'video'; break;
                case 3: params.channel = 'token'; break;
                default: break;
            }
        }

        let shareQuery = `share_id=${shareConfig.shareId}&share_tag=${positionTag}&invite_tag=${userData.userTag}`;
        if (params.query) {
            shareQuery = `${params.query}&${shareQuery}`;
        }
        gg.shareAppMessage({
            title: params.title || params.shareTitle || shareConfig.shareTitle,
            desc,
            imageUrl: params.imageUrl || shareConfig.imageUrl || undefined,
            query: shareQuery,
            imageUrlId: params.imageUrlId || shareConfig.imageUrlId || undefined,
            withShareTicket: params.withShareTicket || shareConfig.withShareTicket || undefined,
            toCurrentGroup,
            path: params.path || shareConfig.path || undefined,
            channel: params.channel || shareConfig.channel || undefined,
            success: (res) => {
                sdkConfig.useNewServer ? getShareParamsFromServerNew() : getShareParamsFromServer();
                callback && callback(undefined, res);
            },
            fail: (err) => { callback && callback(err, undefined); },
            complete: (res) => { },
        });
    };

    /**
      * 显示广告
      * @param {*, positionTag, scatter, configKey, adLoadCallback,adCloseCallback,adType, isCacheFirst, site, params. } params 
      */
    sdk.showAd = (params) => {
        if (gg.isH5) {
            gg.log('显示广告');
            params.adCloseCallback && params.adCloseCallback(null, { isEnded: true });
            return { show: () => { }, hide: () => { } };
        };
        params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_play_start', {
            positionTag: params.positionTag || '',
            scatter: params.scatter,
        });

        const isCacheFirst = params.isCacheFirst || true;
        let adUnitId = params.adUnitId || adConfigs[params.configKey] || getAdUnitId(params.adType, isCacheFirst);
        if (gg.isEmptyString(adUnitId)) {
            gg.error('广告位ID不能为空！', params, adConfigs);
            return null;
        }

        params.adUnitId = adUnitId;
        params.size = params.size;
        params.orientation = params.orientation || 'landscape';
        params.style = params.style;
        const adView = getADViewInstance(params);
        adView && (adView.adLoadCallback = params.adLoadCallback, adView.adCloseCallback = params.adCloseCallback);

        if (params.isDelayShow) { return adView; }

        if (adView) {
            const res = adView.show();
            if (res) {
                res.then(() => {
                    params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_play_succ', {
                        positionTag: params.positionTag || '',
                        scatter: params.scatter,
                    });
                }).catch((err) => {
                    isDebug && gg.log('广告播放失败,自动加载一次');
                    let loadAdToShow = () => {
                        adView.load && adView.load().then(() => {
                            isDebug && gg.log('广告自动加载成功,自动播放');
                            adView.show().then(() => {
                                params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_play_succ', {
                                    positionTag: params.positionTag || '',
                                    scatter: params.scatter,
                                });
                            }).catch((err) => {
                                params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_play_fail', {
                                    errmsg: err.errMsg,
                                    positionTag: params.positionTag || '',
                                    scatter: params.scatter,
                                });
                            });
                        }).catch((err) => {
                            params.adType === AdType.REWARDED_VIDEO && sdk.sendEvent('rewarded_video_play_fail', {
                                errmsg: err.errMsg,
                                positionTag: params.positionTag || '',
                                scatter: params.scatter,
                            });
                        });
                    };

                    if (gg.isQuickGameVIVO) {
                        setTimeout(() => {
                            loadAdToShow();
                            loadAdToShow = undefined;
                        }, 1200);
                    } else {
                        loadAdToShow();
                        loadAdToShow = undefined;
                    }
                });
            }
        }
        return adView;
    };

    /**
     * 隐藏广告
     * @param {*, positionTag, adType } params 
     */
    sdk.hideAd = (params) => {
        if (params && params.adType && (params.adType !== AdType.BANNER || params.adType !== AdType.CUSTOM)) {
            return gg.error('hideAd 只支持 banner和NARIVE  广告', params);
        }
        const adView = getADViewInstance(params);
        adView && adView.hide();
    };

    /**
       * 刷新banner
       * @param {*, positionTag, adType} params 
       * @param {string} positionTag 
       */
    sdk.updateBanner = (params, positionTag, banner) => {
        if (params && params.adType && params.adType !== AdType.BANNER) { return gg.error('updateBanner 只支持 banner 广告', params); }
        sdk.destroyAd({ positionTag: `${positionTag}`, adType: AdType.BANNER }, banner);
        try {
            banner = sdk.showAd({
                positionTag: `${positionTag}`,
                adType: AdType.BANNER,
                isCacheFirst: true,
                site: gg.sdk.CustomType.BANNER_BOTTOM
            });
            return banner;
        } catch (error) { return banner; }
    };



    /**
    * 是否是今天
    * @param time 时间戳
    * @param isMillisecond 是否是毫秒时间戳
    */
    const isToday = (time, isMillisecond) => {
        const isMilliSecond = isMillisecond || false;
        const date = new Date(time * (isMilliSecond ? 1 : 1000));
        const today = new Date();
        // 如果是今天注册
        return date.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear();
    };

    /** 获取SDK初始化配置 */
    sdk.getInitConfig = () => {
        return { ...sdkConfig };
    };

    /** 获取用户信息 */
    sdk.getUserInfo = () => {
        return { ...userData };
    };

    /** 是否已登录 */
    sdk.isLogin = () => {
        return !!isLogined;
    };

    /**获取游戏版本号*/
    sdk.getAppVersion = () => {
        return sdkConfig.APP_VERSION;
    };

    /** 获取游戏内容基础数据 */
    sdk.getRemoteConfig = () => {
        return { ...serverConfig };
    };

    sdk.getPreConfigFromeServer = () => {
        return sdkConfig.useNewServer ? getPreConfigFromeServerNew() : getPreConfigFromeServer();
    };

    //=======================统计埋点=======================
    let sendEventLogs = [];
    const eventCommonParams = {
    };

    const initSendEvent = () => {
        eventCommonParams.equipment_brand = systemInfo.brand || 'unknown';      // 设备品牌
        eventCommonParams.equipment_model = systemInfo.model || 'unknown';      // 设备型号
        eventCommonParams.app_version = systemInfo.version || '0.0.0';          // app版本号
        eventCommonParams.game_version = sdkConfig.APP_VERSION || '0.0.0';      // 游戏版本号
        eventCommonParams.device_id = userData.userTag;                         // 设备id
        eventCommonParams.os = cc.sys.os;                                       // 操作系统
        eventCommonParams.os_version = systemInfo.system || 'unknown';          // 操作系统版本
        eventCommonParams.temp_gem = 0;                                         // 钻石数量
        eventCommonParams.temp_gold = 0;                                        // 金币数量
        eventCommonParams.temp_points = 0;                                      // 积分数量
        eventCommonParams.game_mode = 1;                                        // 游戏模式
        eventCommonParams.max_chapter_level = 1;                                // 章节关卡波数
        eventCommonParams.max_chapter = 1;                                      // 章节
        eventCommonParams.role_level = 1;                                       // 等级
    };
    const getEventCommonParams = (params) => {
        return { ...eventCommonParams, ...params };
    };
    sdk.setEventCommonParams = (key, value) => {
        eventCommonParams[key] = value;
    };
    sdk.sendEventUserSetOnce = (params) => {
        return sdk.sendEvent('userSetOnce', params, 'userSetOnce');
    };
    sdk.sendEventUserSet = (params) => {
        // 部分用户数据需要同步给公共事件属性
        const keyMap = {
            current_level: 'role_level',
            current_chapter: 'max_chapter',
            current_chapter_level: 'max_chapter_level',
            current_coin: 'temp_gold',
            current_gem: 'temp_gem',
            current_points: 'temp_points',
        };
        let newKey;
        for (const key in params) {
            newKey = keyMap[key];
            newKey && sdk.setEventCommonParams(newKey, params[key]);
        }

        return sdk.sendEvent('userSet', params, 'userSet');
    };
    /** 数数打点 */
    let sendEventTime = 0;
    sdk.sendEvent = (name, params = {}, table = "track", force = false) => {
        const SWITCH_SEND_ANALYSIS = serverConfig.SWITCH_SEND_ANALYSIS || serverConfig.SWITCH_SHUSHU_ANALYSIS;
        if (!force && (!SWITCH_SEND_ANALYSIS || SWITCH_SEND_ANALYSIS === 3)) return gg.warn('sendEvent:', `serverConfig.SWITCH_SEND_ANALYSIS is ${serverConfig.SWITCH_SEND_ANALYSIS}.`);
        const content = {
            event: name,
            accountId: userData.userTag,
            properties: getEventCommonParams(params)
        };
        const _event_time = new Date().getTime();
        sendEventLogs.push({ table, content, _event_time });
        isDebug && gg.info('sendEvent:', { table, content, _event_time });
        if (!userData.openId) { return gg.log("sendEvent delay:", name, 'openId is null'); }

        // 控制上报时间
        const time = Date.now(); // 10s一次
        if (!force && (time - sendEventTime < 10 * 1000)) { return; }
        sendEventTime = time;   // 重置时间
        isDebug && gg.info('sendEvent: post', sendEventTime);

        // 开始上报
        const sendEventLogsCopy = sendEventLogs;
        sendEventLogs = [];
        sdk.post(`${APP_SERVER_HOST_ANALYSIS}/log/mh/post`, {
            apiData: {
                appID: sdkConfig.appId,
                redisKey: gg.isQuickGameOPPO ? 'framework-log:mobile-oppo-bi' : undefined
            },
            logs: sendEventLogsCopy
        }, {}, true).then(() => { }).catch((err) => {
            console.error('sendEvent error:', err);
            for (let i = 0; i < sendEventLogsCopy.length; i++) {
                sendEventLogs.push(sendEventLogsCopy[i]);
            }
        });
    };






    //=======================服务器榜单=======================
    /**获取榜单信息 */
    sdk.getRankData = async (type) => {
        const res = await sdk.post(`${APP_SERVER_HOST_NEW}/rank/mh/get-rank`, { type: type });
        return res;
    };

    /** 上报数值 */
    sdk.postValues = async (values) => {
        await sdk.post(`${APP_SERVER_HOST_NEW}/prop/mh/post-values`, { values });
    };

    /** 获取玩家头像信息等 */
    sdk.findUsers = async (ids) => {
        const res = await sdk.post(`${APP_SERVER_HOST_NEW}/account/mh/find-users`, { ids });
        return res;
    };

    const getButtonStyle = (buttonNode, style) => {
        style.left = style.left ?? 0;
        style.top = style.top ?? 0;
        style.debug = style.debug ?? false;

        const gameSize = cc.view.getVisibleSize();
        const frameWidth = screen.width;
        const ratio = frameWidth / gameSize.width;

        return {
            left: ((buttonNode.worldPosition.x - buttonNode.width / 2) * ratio) + style.left,
            top: (screen.height - (buttonNode.worldPosition.y * ratio) - buttonNode.height / 2) + style.top,
            width: buttonNode.width * ratio + 5,
            height: buttonNode.height * ratio + 5,
            backgroundColor: style.debug ? '#ff0000' : null,
            borderRadius: 4
        };
    };

    /** 授权微信头像同步至服务端 */
    sdk.authorization = async (callback, buttonNode, isUpload, style) => {
        callback = callback || (() => { });
        isUpload = !!isUpload;

        return new Promise((s, f) => {
            // 查询玩家是否已经授权
            gg.getSetting({
                lang: "zh_CN",
                success: (res) => {
                    // 已授权
                    if (res.authSetting['scope.userInfo']) {
                        callback(undefined, res);
                        return s({ destroy: () => { } });
                    }
                    if (!buttonNode) {
                        callback({ msg: 'buttonNode is null.' });
                        return f({ msg: 'buttonNode is null.' });
                    }

                    // 创建微信按钮
                    const button = gg.createUserInfoButton({
                        type: 'text',
                        text: '',
                        style: getButtonStyle(buttonNode, style)
                    });
                    button.onTap(async (res) => {
                        if (!res.rawData) { return callback({ msg: 'res.rawData is null.' }); }
                        button.destroy();
                        if (isUpload) {
                            await sdk.post(`${APP_SERVER_HOST_NEW}/account/mh/update-by-leisure`, {
                                headAddress: res.userInfo.avatarUrl,
                                nickname: res.userInfo.nickName
                            });
                        }
                        callback(undefined, res);
                    });
                    s(button);
                }
            });
        });
    };




    //=======================订阅内容=======================
    /** 订阅版本更新内容 */
    sdk.onSubscriptionUpgrede = () => {
        // if (gg.getTodayValue('isSubscriptionUpgrede')) return;
        // gg.setTodayValue('isSubscriptionUpgrede', true);
        return new Promise((s, f) => {
            gg.requestSubscribeSystemMessage({
                msgTypeList: ['SYS_MSG_TYPE_WHATS_NEW'],
                success: (res) => { s(res); },
                fail: (err) => { f(err); },
            });
        });
    };

    /** 检测是否玩家已订阅 */
    sdk.onCheckSubscription = () => {
        return new Promise((s, f) => {
            gg.getSetting({
                withSubscriptions: true,
                success: (res) => {
                    if (res.subscriptionsSetting.mainSwitch) {
                        const tmplIds = sdkConfig.subscriptionIds || [];
                        const ok = tmplIds.every(r => res.subscriptionsSetting.itemSettings[r.id] == 'accept');
                        ok ? s(true) : s(false);
                    } else {
                        s(false);
                    }
                },
                fail: (err) => {
                    f(err);
                }
            });
        });
    };

    sdk.onSubscription = async () => {
        const tmplIds = subscriptionIds || [];
        let idArr = [];
        for (let i = 0; i < tmplIds.length; i++) {
            let data = tmplIds[i];
            idArr[i] = data['id'];
        }

        const getTimeStamp = (time) => {
            return Math.floor(Date.now() / 1000 + (time * 3600) + 86400);
        };
        return new Promise((s, f) => {
            gg.requestSubscribeMessage({
                tmplIds: idArr,
                success: async (res) => {
                    let isSuccess = true;
                    const template_ids = [];
                    tmplIds.forEach(r => {
                        if (res[tmplIds[r.id]] === 'accept') {
                            template_ids.push({
                                id: r.id,
                                time: getTimeStamp(r.count)
                            });
                        } else {
                            isSuccess = false;
                        }
                    });
                    await sdk.post(`https://game-api.feigo.fun/api/user/user-push-power`, template_ids);
                    gg.event.emit(isSuccess ? 'SUBSCRIPTION_SUCCESS' : 'SUBSCRIPTION_FAIL');
                    s({ isSuccess, template_ids, ...res });
                },
                fail: (err) => {
                    isDebug && gg.error(err);
                    gg.event.emit('SUBSCRIPTION_FAIL');
                    f({ tmplIds, err });
                }
            });
        });
    };





    //=======================游戏录屏=======================

    let gameRecorderManager;
    let gameRecorderVideoPath = '';
    /** 初始化录屏 */
    const initRecorder = () => {
        gameRecorderManager = gg.getGameRecorderManager();
        gameRecorderManager.onStart((res) => { });
        gameRecorderManager.onStop((res) => { gameRecorderVideoPath = res.videoPath; });
    }

    /** 开始录屏 */
    sdk.recorderStart = (duration) => {
        if (!gg.isMiniGameTT) { return gg.warn('该平台暂不支持录屏.'); }
        if (!gameRecorderManager) { initRecorder(); }
        gameRecorderManager.start({ duration });
    }

    /** 停止录屏 */
    sdk.recorderStop = () => {
        if (!gg.isMiniGameTT) { return gg.warn('该平台暂不支持录屏.'); }
        gameRecorderManager.stop();
    }

    /** 分享录屏 */
    sdk.recorderShare = (templateId) => {
        if (!gg.isMiniGameTT) { return gg.warn('该平台暂不支持录屏.'); }
        templateId = templateId || 'gjo9ri2b2kd3kguuh6';

        isDebug && gg.log('录屏分享的templateId：', templateId);

        gg.shareAppMessage({
            templateId,
            channel: "video",
            title: shareConfig.share_title,
            // desc: "",
            imageUrl: shareConfig.shareImgUrl,
            query: `type=videoshare&share_tag=视频分享&invite_tag=${userData.userTag}`,
            extra: {
                videoPath: gameRecorderVideoPath,
                video_title: '',
                hashtag_list: [sdkConfig.GAME_NAME],
                videoTopic: [sdkConfig.GAME_NAME],
            },
            success() { gg.showToast('本局视频已分享', 1.5); },
            fail(e) { gg.showToast('分享视频失败', 1.5); }
        });
    }



    gg.sdk = { toString: () => { return '[object undefined]'; }, ...sdk };
    window.fl = window.fl || {};
    gg.sdk = gg.sdk;
    gg.AdType = AdType;
    gg.CustomType = CustomType;
}